{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Ungraded Lab - Regularized Cost\n",
    "\n",
    "In this lab we will extend the previous cost function with a regularization term."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from lab_utils import sigmoid"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cost function for regularized logistic regression\n",
    "\n",
    "Below, we will implement the cost function for regularized logistic regression.\n",
    "\n",
    "Recall that for regularized logistic regression, the cost function is of the form\n",
    "$$J(\\mathbf{w}) = \\frac{1}{m}  \\sum_{i=0}^{m-1} \\left[ -y^{(i)} \\log\\left(f_{\\mathbf{w}}\\left( \\mathbf{x}^{(i)} \\right) \\right) - \\left( 1 - y^{(i)}\\right) \\log \\left( 1 - f_{\\mathbf{w}}\\left( \\mathbf{x}^{(i)} \\right) \\right) \\right] + \\frac{\\lambda}{2m}  \\sum_{j=1}^{n} w_j^2$$\n",
    "\n",
    "Compare this to the cost function without regularization (which you implemented in  a previous lab), which is of the form \n",
    "\n",
    "$$ J(\\mathbf{w}) = \\frac{1}{m}\\sum_{i=0}^{m-1} \\left[ (-y^{(i)} \\log\\left(f_{\\mathbf{w}}\\left( \\mathbf{x}^{(i)} \\right) \\right) - \\left( 1 - y^{(i)}\\right) \\log \\left( 1 - f_{\\mathbf{w}}\\left( \\mathbf{x}^{(i)} \\right) \\right)\\right]$$\n",
    "\n",
    "The difference is the regularization term, which is $$\\frac{\\lambda}{2m}  \\sum_{j=1}^n w_j^2$$\n",
    "\n",
    "Note that summation starts from $j = 1$. That is, you should not regularize the parameter $w_0$. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Please complete the `compute_cost_reg` function to:\n",
    "- Calculate the cost over all examples in the training set\n",
    "    - Loop over all examples in the training set. Create a variable outside the loop to store the total cost\n",
    "    - Inside the loop, calculate the cost for each training example exactly as you did in the `compute_cost` function above - \n",
    "        - Calculate `z`\n",
    "        $$\n",
    "        z =  w_0x_0^{(i)} + w_1x_1^{(i)} + w_2x_2^{(i)} = \\mathbf{w} \\cdot \\mathbf{x}^{(i)}\n",
    "        $$\n",
    "        - Predict `f` where `g` is the sigmoid function\n",
    "        $$\n",
    "        f =  g(z)\n",
    "        $$\n",
    "        - Calculate the cost for each example\n",
    "\n",
    "        $cost =  (-y^{(i)} * \\log(f)) - ((1 - y^{(i)})\\log( 1 - f))$\n",
    "    \n",
    "        - Add this cost to the total cost variable created outside the loop\n",
    "        \n",
    "        \n",
    "- Calculate the regularization term by looping over `n` (number of features). Create a variable outside the loop to store the regularization cost\n",
    "    - Make sure to start the loop at 1 (not 0) since you don't want to use the $w[0]$ term\n",
    "    - Inside the loop, calculate `w_j**2`\n",
    "    - Add this to the regularization cost variable\n",
    "    \n",
    "    \n",
    "- Get the total sum as the sum of the outputs from the two loops, that is add \n",
    "    - sum of cost from all the training examples divided by the number of examples\n",
    "    - sum of regularization cost from iterating over $w$ multiplied by $\\frac{\\lambda}{2m}$\n",
    "\n",
    "As you are doing this, remember that the variables X and y are not scalar values but matrices of shape ($m, n+1$) and ($𝑚$, ) respectively, where  $𝑛$ is the number of features and $𝑚$ is the number of training examples.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<details>\n",
    "  <summary><font size=\"2\" color=\"darkgreen\"><b>Hints</b></font></summary>\n",
    "       \n",
    "    ```     \n",
    "def compute_cost_reg(X, y, w, lambda_=1): \n",
    "    \"\"\"\n",
    "    Computes the cost for regularized logistic regression.\n",
    "    \n",
    "    Parameters\n",
    "    ----------\n",
    "    X : array_like\n",
    "        Shape (m, n+1) \n",
    "    \n",
    "    y : array_like\n",
    "        Shape (m,) \n",
    "    \n",
    "    w : array_like\n",
    "        Parameters of the model\n",
    "        Shape (n+1,)\n",
    "        \n",
    "    lambda_ : float\n",
    "        Controls amount of regularization\n",
    "        Default is set to 1\n",
    "    \n",
    "    Returns\n",
    "    -------\n",
    "    total_cost : float\n",
    "        The cost of using w as the parameter for regularized logistic \n",
    "        regression to fit the data points in X and y\n",
    "    \"\"\"\n",
    "    # number of training examples\n",
    "    m, n = X.shape\n",
    "    \n",
    "    ### START CODE HERE ### \n",
    "    cost_list = []\n",
    "    \n",
    "    for i in range(m):\n",
    "        z = np.dot(w.T, X[i])\n",
    "        f = sigmoid(z)\n",
    "        cost = -y[i]*np.log(f) - (1-y[i])*np.log(1-f)        \n",
    "        cost_list.append(cost)\n",
    "        \n",
    "    total_cost = (1/m)* sum(cost_list)\n",
    "    \n",
    "    reg_cost = 0\n",
    "    for j in range(1, n):\n",
    "        reg_cost += (w[j]**2)\n",
    "    \n",
    "    total_cost += (lambda_/(2*m))*reg_cost\n",
    "    ### END CODE HERE ###\n",
    "    \n",
    "    return total_cost\n",
    "   ```    \n",
    "</details>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_cost_reg(X, y, w, lambda_=1): \n",
    "    \"\"\"\n",
    "    Computes the cost for regularized logistic regression.\n",
    "    \n",
    "    Parameters\n",
    "    ----------\n",
    "    X : array_like\n",
    "        Shape (m, n+1) \n",
    "    \n",
    "    y : array_like\n",
    "        Shape (m,) \n",
    "    \n",
    "    w : array_like\n",
    "        Parameters of the model\n",
    "        Shape (n+1,)\n",
    "        \n",
    "    lambda_ : float\n",
    "        Controls amount of regularization\n",
    "        Default is set to 1\n",
    "    \n",
    "    Returns\n",
    "    -------\n",
    "    total_cost : float\n",
    "        The cost of using w as the parameter for regularized logistic \n",
    "        regression to fit the data points in X and y\n",
    "    \"\"\"\n",
    "    # number of training examples\n",
    "    m, n = X.shape\n",
    "    \n",
    "    ### START CODE HERE ### \n",
    "\n",
    "    ### END CODE HERE ###\n",
    "    \n",
    "    return total_cost"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run the cell below to check your implementation of the `compute_cost_reg` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Regularized cost at initial w: 1.040147888237227\n"
     ]
    }
   ],
   "source": [
    "np.random.seed(1)\n",
    "X_tmp = np.random.rand(5,6)\n",
    "y_tmp = np.array([0,1,0,1,0])\n",
    "initial_w = np.random.rand(X_tmp.shape[1])\n",
    "lambda_ = 1\n",
    "cost = compute_cost_reg(X_tmp, y_tmp, initial_w, lambda_)\n",
    "\n",
    "print(\"Regularized cost at initial w:\", cost)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Expected Output**:\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <b>Regularized cost at initial w: </b> 1.040147888237227 </td>\n",
    "  </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
